/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package gblend.largegraph;

import gblend.adjlistgraph.ALGraph;
import gblend.adjlistgraph.FsgIdEntry;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Vector;

/**
 *
 * @author HO HOANG HUNG
 */
public class CombineGraph {

    /**
     * combine 2 graph (in file) into a single graph, result path should not contain
     * / and must exist.
     * All path must use / instead of \
     * File format is the one after use metis.
     * @param resPath
     * @param path1
     * @param path2
     * @return
     
    public static String combineGraphs(String resPath, String path1, String path2) {
        int l1 = path1.lastIndexOf("/");
        int l2 = path2.lastIndexOf("/");
        String file1 = path1.substring(l1 + 1);
        String file2 = path2.substring(l2 + 1);
        String[] gidlist1 = file1.split("-");
        String[] gidlist2 = file2.split("-");
        Vector<Integer> gidlistC = new Vector<Integer>();
        HashSet<String> gidl1 = new HashSet<String>(), gidl2 = new HashSet<String>();
        for (int i = 0; i < gidlist1.length; i++) {
            gidl1.add(gidlist1[i]);
        }
        for (int i = 0; i < gidlist2.length; i++) {
            //  System.out.println(gidlist2[i]);
            gidl2.add(gidlist2[i]);
        }
        gidl1.addAll(gidl2);
        Iterator<String> gidlit = gidl1.iterator();
        while (gidlit.hasNext()) {
            String temp = gidlit.next();
            System.out.println(temp);
            gidlistC.add(Integer.parseInt(temp));
        }
        Collections.sort(gidlistC);
        StringBuffer resName = new StringBuffer(gidlistC.firstElement().toString());
        for (int i = 1; i < gidlistC.size(); i++) {
            resName.append("-" + gidlistC.get(i));
        }
        File fl1 = new File(path1);
        File fl2 = new File(path2);
        File res = new File(resPath + "/" + resName);
        if (res.exists()) {
            System.out.println("File alr exists 2");
            return resName.toString();
        }

        HashMap<Integer, Integer> degreeList = new HashMap<Integer, Integer>();
        HashMap<Integer, Vector<Integer>> adjList = new HashMap<Integer, Vector<Integer>>();

        BufferedInputStream bin1, bin2;
        try {
            bin1 = new BufferedInputStream(new FileInputStream(fl1));
            BufferedReader br1 = new BufferedReader(new InputStreamReader(bin1));
            String strLine1 = br1.readLine();
            String[] strplit1 = strLine1.split("\\s");
            int nnum1 = Integer.parseInt(strplit1[1]);
            int a = 1, curId1;
            while (a <= nnum1) {
                strLine1 = br1.readLine();
                strplit1 = strLine1.trim().split("\\s");
                curId1 = Integer.parseInt(strplit1[0]);
                int length = strplit1.length - 1;
                int degree = Integer.parseInt(strplit1[length]);
                Vector<Integer> al = new Vector<Integer>(length - 1);
                for (int i = 1; i < length; i++) {
                    al.add(Integer.parseInt(strplit1[i]));
                }
                degreeList.put(curId1, degree);
                adjList.put(curId1, al);
                a++;
            }
            bin1.close();
            br1.close();
            bin2 = new BufferedInputStream(new FileInputStream(fl2));
            BufferedReader br2 = new BufferedReader(new InputStreamReader(bin2));
            String strLine2 = br2.readLine();
            String[] strplit2 = strLine2.split("\\s");
            int nnum2 = Integer.parseInt(strplit2[1]);
            int b = 1, curId2;
            while (b <= nnum2) {
                strLine2 = br2.readLine();
                strplit2 = strLine2.trim().split("\\s");
                curId2 = Integer.parseInt(strplit2[0]);
                int length = strplit2.length - 1;
                int degree = Integer.parseInt(strplit2[length]);
                degreeList.put(curId2, degree);
                Vector<Integer> al = adjList.get(curId2);
                if (al == null) {
                    al = new Vector<Integer>(length - 1);
                    for (int i = 1; i < length; i++) {
                        al.add(Integer.parseInt(strplit2[i]));
                    }
                    adjList.put(curId2, al);
                } else {
                    for (int i = 1; i < length; i++) {
                        al.add(Integer.parseInt(strplit2[i]));
                    }
                }
                b++;
            }
            bin2.close();
            br2.close();
            //Print file
            BufferedOutputStream bos1 = null;
            bos1 = new BufferedOutputStream(new FileOutputStream(res));
            PrintStream q1 = new PrintStream(bos1);
            Vector<Integer> indexs = new Vector<Integer>(degreeList.keySet());
            Collections.sort(indexs);
            Integer[] index = indexs.toArray(new Integer[0]);
            int idsize = index.length;
            q1.println("c " + idsize);
            Vector<Integer> boundList = new Vector<Integer>();
            for (int i = 0; i < idsize; i++) {
                Vector<Integer> adj = adjList.get(index[i]);
                Collections.sort(adj);
                int degree = degreeList.get(index[i]);
                if (adj.size() < degree) {
                    boundList.add(index[i]);
                }
                StringBuffer line = new StringBuffer(index[i].toString());
                Enumeration<Integer> adje = adj.elements();
                while (adje.hasMoreElements()) {
                    line.append(" " + adje.nextElement().toString());
                }
                q1.println(line.toString() + " " + degree);
            }
            q1.println();
            StringBuffer line = new StringBuffer();
            Enumeration<Integer> bounde = boundList.elements();
            while (bounde.hasMoreElements()) {
                line.append(bounde.nextElement().toString() + " ");
            }
            q1.println(line);
            q1.flush();
            q1.close();

        } catch (Exception e) {
            e.printStackTrace();
        }
        return resName.toString();
    }*/

    private static String combineGraphsSortedName(String resPath, Vector<Integer> path1s, int path2) {
        Vector<Integer> path1 = new Vector<Integer>(path1s);
        // int l1 = path1.lastIndexOf("/");
        // int l2 = path2.lastIndexOf("/");
        StringBuffer file1 =null;
        if(path1.size()==1){
            file1= new StringBuffer(resPath + "/" + path1.firstElement());
        }else{
            file1= new StringBuffer(resPath + "extra/" + path1.firstElement());
        }
        for (int i = 1; i < path1.size(); i++) {
            file1.append("-" + path1.elementAt(i));
        }
        String file2 = resPath + "/" + path2;

        //Vector<Integer> gidlistC = new Vector<Integer>();
        //     HashSet<String> gidl1 = new HashSet<String>(), gidl2 = new HashSet<String>();
        if (!(path1.contains(path2))) {
            path1.add(path2);
        }
        //gidl1.addAll(gidl2);
        //Iterator<String> gidlit = gidl1.iterator();
        /*while (gidlit.hasNext()) {
        String temp = gidlit.next();
        System.out.println(temp);
        gidlistC.add(Integer.parseInt(temp));
        }*/
        Collections.sort(path1);
        StringBuffer resName = new StringBuffer(path1.firstElement().toString());
        for (int i = 1; i < path1.size(); i++) {
            resName.append("-" + path1.get(i));
        }
        File fl1 = new File(file1.toString());
        File fl2 = new File(file2);
        File res = new File(resPath + "extra/" + resName);
        if (res.exists()) {
            System.out.println("File alr exists 1");
            return resName.toString();
        }

        HashMap<Integer, Integer> degreeList = new HashMap<Integer, Integer>();
        HashMap<Integer, Vector<Integer>> adjList = new HashMap<Integer, Vector<Integer>>();

        BufferedInputStream bin1, bin2;
        try {
            bin1 = new BufferedInputStream(new FileInputStream(fl1));
            BufferedReader br1 = new BufferedReader(new InputStreamReader(bin1));
            String strLine1 = br1.readLine();
            String[] strplit1 = strLine1.split("\\s");
            int nnum1 = Integer.parseInt(strplit1[1]);
            int a = 1, curId1;
            while (a <= nnum1) {
                strLine1 = br1.readLine();
                strplit1 = strLine1.trim().split("\\s");
                curId1 = Integer.parseInt(strplit1[0]);
                int length = strplit1.length - 1;
                int degree = Integer.parseInt(strplit1[length]);
                Vector<Integer> al = new Vector<Integer>(length - 1);
                for (int i = 1; i < length; i++) {
                    al.add(Integer.parseInt(strplit1[i]));
                }
                degreeList.put(curId1, degree);
                adjList.put(curId1, al);
                a++;
            }
            bin1.close();
            br1.close();
            bin2 = new BufferedInputStream(new FileInputStream(fl2));
            BufferedReader br2 = new BufferedReader(new InputStreamReader(bin2));
            String strLine2 = br2.readLine();
            String[] strplit2 = strLine2.split("\\s");
            int nnum2 = Integer.parseInt(strplit2[1]);
            int b = 1, curId2;
            while (b <= nnum2) {
                strLine2 = br2.readLine();
                strplit2 = strLine2.trim().split("\\s");
                curId2 = Integer.parseInt(strplit2[0]);
                int length = strplit2.length - 1;
                int degree = Integer.parseInt(strplit2[length]);
                degreeList.put(curId2, degree);
                Vector<Integer> al = adjList.get(curId2);
                if (al == null) {
                    al = new Vector<Integer>(length - 1);
                    for (int i = 1; i < length; i++) {
                        al.add(Integer.parseInt(strplit2[i]));
                    }
                    adjList.put(curId2, al);
                } else {
                    for (int i = 1; i < length; i++) {
                        al.add(Integer.parseInt(strplit2[i]));
                    }
                }
                b++;
            }
            bin2.close();
            br2.close();
            //Print file
            BufferedOutputStream bos1 = null;
            bos1 = new BufferedOutputStream(new FileOutputStream(res));
            PrintStream q1 = new PrintStream(bos1);
            Vector<Integer> indexs = new Vector<Integer>(degreeList.keySet());
            Collections.sort(indexs);
            Integer[] index = indexs.toArray(new Integer[0]);
            int idsize = index.length;
            q1.println("c " + idsize);
            Vector<Integer> boundList = new Vector<Integer>();
            for (int i = 0; i < idsize; i++) {
                Vector<Integer> adj = adjList.get(index[i]);
                Collections.sort(adj);
                int degree = degreeList.get(index[i]);
                if (adj.size() < degree) {
                    boundList.add(index[i]);
                }
                StringBuffer line = new StringBuffer(index[i].toString());
                Enumeration<Integer> adje = adj.elements();
                while (adje.hasMoreElements()) {
                    line.append(" " + adje.nextElement().toString());
                }
                q1.println(line.toString() + " " + degree);
            }
            q1.println();
            StringBuffer line = new StringBuffer();
            Enumeration<Integer> bounde = boundList.elements();
            while (bounde.hasMoreElements()) {
                line.append(bounde.nextElement().toString() + " ");
            }
            q1.println(line);
            q1.flush();
            q1.close();

        } catch (Exception e) {
            e.printStackTrace();
        }
        return resName.toString();
    }

    private static Vector<Integer> combine(String[] strplit1, String[] strplit2) {
        Vector<Integer> res = new Vector<Integer>();
        int a = 1, b = 1, length1 = strplit1.length - 2, length2 = strplit2.length - 2;
        int cur1 = Integer.parseInt(strplit1[a]);
        int cur2 = Integer.parseInt(strplit2[b]);
        while ((a <= length1) && (b <= length2)) {
            if (cur1 > cur2) {
                res.add(cur2);
                if (b == length2) {
                    res.add(cur1);
                    if (a == length1) {
                        break;
                    } else {
                        a++;
                        cur1 = Integer.parseInt(strplit1[a]);
                    }
                } else {
                    b++;
                    cur2 = Integer.parseInt(strplit2[b]);
                }
            } else if (cur1 < cur2) {
                res.add(cur1);
                if (a == length1) {
                    res.add(cur2);
                    if (b == length2) {
                        break;
                    } else {
                        b++;
                        cur2 = Integer.parseInt(strplit2[b]);
                    }
                } else {
                    a++;
                    cur1 = Integer.parseInt(strplit1[a]);
                }
            } else {
                res.add(cur1);
                a++;
                if (a <= length1) {
                    cur1 = Integer.parseInt(strplit1[a]);
                }
                b++;
                if (b <= length2) {
                    cur2 = Integer.parseInt(strplit2[b]);
                }
            }
        }
        return res;
    }

    /*
     * Test
     */
    public static void main(String[] args) {
        System.out.println("Test CombineGraph");
     //   combineGraphs("data", "data/594", "data/5940799");
        System.out.println("Done");
    }

    /**
     *
     * @param path MUST end with '/'
     * @param entry1
     * @param entry2
     * @return File Name
     */
    public static String combineGraphs(String path, FsgIdEntry entry1, FsgIdEntry entry2) {
     //   System.out.println("entry1="+entry1.toString()+" entry2="+entry2.toString());
        HashSet<Integer> set1 = new HashSet<Integer>(entry1.getGraphId());
        HashSet<Integer> set2 = new HashSet<Integer>(entry2.getGraphId());
        set1.addAll(set2);
        String path2 = path.substring(0, path.length() - 1);
        Vector<Integer> gIdList = new Vector<Integer>(set1);
        Collections.sort(gIdList);
        Vector<Integer> first = new Vector<Integer>();
        int size = gIdList.size() - 1;
        String res = null;

        for (int i = 0; i < size; i++) {
          //  System.out.println("gidList(i)="+gIdList.get(i)+" gidList(i+1)="+gIdList.get(i+1));
            first.add(gIdList.get(i));
            res = combineGraphsSortedName(path2, first, gIdList.get(i + 1));
            // first.append("-");
        }
        //first.append(gIdList.lastElement());
        return res;
    }
}
